#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>


static pthread_key_t key;

static pthread_once_t init_once = PTHREAD_ONCE_INIT;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* specific_data[2] ={0};

void echomsg(char* a) 
{
	printf( "FREE.\n" );
	free( a );

	return ;	
}

void init( )

{

	puts("this is pthread once init function, key is created");

	pthread_key_create( &key, free );

}

void* thread( void* para )

{

	pthread_once( &init_once, init );

	pthread_t t = pthread_self();

	printf("thread %d\n", t);

	char* sp = (char*)malloc( 10 );

	pthread_setspecific( key, (void*)sp );

	printf("thread %d: specific data: %d\n", (unsigned long)t, (unsigned long)sp );


	//store thread specific data into array
	pthread_mutex_lock(&mutex);

	int i=0;

	if ( !specific_data[0] )

		i = 0;

	else

		i = 1;

	specific_data[i] = sp;

	*sp = i;

	pthread_mutex_unlock(&mutex);


	if( i == 0 )

	{

		sleep(1);


		//after one thread sleeps, we are sure ,all thread have stored their specific data into
		//the array

		printf("thread %d, before editing, *(specific_data[0])=%d, *(specific_data[1])=%d\n",(unsigned long)t, *((char*)specific_data[0]),*((char*)specific_data[1]) );

		*((char*)specific_data[1]) = 0;

		printf("thread %d, after editing, *(specific_data[0])=%d, *(specific_data[1])=%d\n",(unsigned long)t, *((char*)specific_data[0]),*((char*)specific_data[1]) );


	}

	else

		sleep(10);

	pthread_exit(0);

}



int main()

{

	pthread_t t1,t2;

	void *st1, *st2;

	pthread_create( &t1, NULL, thread, NULL );

	pthread_create( &t2, NULL, thread, NULL );


	pthread_join( t1, &st1 );

	pthread_join( t2, &st2 );

	printf("thread %u returns %d\n", t1, (unsigned long)st1 );

	printf("thread %u returns %d\n", t2, (unsigned long )st2);

	return 0;

}


